package Linguo;

import java.awt.Rectangle;
import java.util.ArrayList;

import GUI.GUIJuego;
import Objetos.*;
import Pisos.*;
import Robots.*;



/**
 * The Class Mapa.
 */

public class Mapa {

	/** Atributo offset. */
	protected final int OFFSET = 30;
	
	/** Atributo space. */
	protected final int SPACE = 20;



	/** Atributo x inicial, coordenada x del robot en el comienzo del juego*/
	protected int xInicial;
	
	/** Atributo y inicial, coordenada y del robot en el comienzo del juego*/
	protected int yInicial;
	
	//** Atributo x final, coordenada x de la llegada del juego.*/
	protected int xFinal;
	
	/** Atributo y final, coordenada y de la llegada del juego. */
	protected int yFinal;

	/** Atributo robot, es el robot que se encuentra en el mapa. */
	protected Robot robot;
	
	/** Atributo tipo robot es la especializacion del robot del mapa.*/
	protected String tipoRobot;

	/** Atributo transitables, lista de transitables del nivel. */
	protected ArrayList <Transitable> transitables = new ArrayList<Transitable>();
	
	/** Atributo intransitables, lista de intransitables del nivel. */
	protected ArrayList<Intransitable> intransitables  = new ArrayList<Intransitable>();
	
	/** Atributo destructibles, lista de destructibles del nivel. */
	protected ArrayList<Destructible> destructibles  = new ArrayList<Destructible>();
	
	/** Atributo indestructibles, lista de indestructibles del nivel. */
	protected ArrayList<Indestructible> indestructibles  = new ArrayList<Indestructible>();
	
	/** Atributo premios, lista de premios del nivel. */
	protected ArrayList<Premio> premios  = new ArrayList<Premio>();
	

	/** Atributo coleccionables, lista de coleccionables del nivel. */
	protected ArrayList <Coleccionable> coleccionables  = new ArrayList <Coleccionable> ();
	
	/** Atributo disparos, lista de disparos del nivel. */
	protected ArrayList<Disparo> disparos  = new ArrayList<Disparo>();
	
	/** Atributo pinturas, lista de pinturas del nivel. */
	protected ArrayList<Pintura> pinturas= new ArrayList<Pintura>();

	/** Atributo w, ancho del mapa. */
	protected int w;
	
	/** Atributo h, alto del mapa. */
	protected int h;

	/** Atributo m, mapeo de clase->imagenes del mapa. */
	protected Mapeo m= new Mapeo();
	
	/** Atributo gui juego. */
	protected GUIJuego guiJuego;

	/** Atributo completed, verdadero si el robot llego a la llegada. */
	protected boolean completed = false;

	/** Atributo puntaje, puntaje del robot. */
	protected int puntaje;


	/** Atributo level, distribucion de los pisos del mapa. */
	protected String level;

	//w = concreto
	//b = balas
	//n = nafta
	//p = puntos
	//s = arena
	//a = agua
	//f = fuego
    //k = cono
    //z = baliza
	//c = caja
	//$ = planta
	//o = asfalto
	//e = pared	

	/** Atributo objetos, distribucion de los objetos del mapa */
protected String objetos;

/**
 * Constructor de la clase mapa.
 *
 * @param gui GUI del juego,
 * @param nivel Arreglo con el nivel del juego
 * @param tipoRobot especificacion del tipo de robot.
 */
public Mapa(GUIJuego gui,String [] nivel, String tipoRobot) {
		
		guiJuego = gui;
		puntaje=0;
		this.tipoRobot = tipoRobot;
				
		level = nivel[0];
		objetos = nivel[1];
		xInicial = Integer.parseInt(nivel[2]);
		yInicial = Integer.parseInt(nivel[3]);
		xFinal = Integer.parseInt(nivel[4]);
		yFinal = Integer.parseInt(nivel[5]);

		initWorld();

	}


/**
 * Distribuye los elementos del juego en las listas que luego seran representadas.
 */
	public final void initWorld() {

		int x = OFFSET;
		int y = OFFSET;

		for(int i = 0 ; i < level.length() ; i++) {

			char item = level.charAt(i);
			char item2 = objetos.charAt(i);

			if(item == '%') {
				y+= SPACE;
				if(this.w < x)
					this.w = x;
				x = OFFSET;
			}
			else if( item == 'w') {
				Indestructible I = new Concreto(x,y,m.get("Concreto"));
				intransitables.add(I);
				indestructibles.add(I);
				x+= SPACE;
			}
			else if( item == 'a') {
				Indestructible I = new Agua(x,y,m.get("Agua"));
				intransitables.add(I);
				indestructibles.add(I);
				x+= SPACE;			
			}
			else if (item == 'f') {
				Indestructible I = new Fuego(x,y,m.get("Fuego"));
				intransitables.add(I);
				indestructibles.add(I);
				x+= SPACE;	
			}
			else if ( item == 'o') {
				Asfalto T = new Asfalto(x,y,m.get("Asfalto"));
				transitables.add(T);
				if( item2 == 'c') {
					crearPremioRandom(x,y);
					Caja c = new Caja(x,y,m.get("Caja"));
					intransitables.add(c);
					destructibles.add(c);

				}
				else if( item2 == 'p') {
					Premio p = new Puntos(x,y,m.get("Puntos"));
					premios.add(p);
				}
				else if( item2 == 'n') {
					Premio p = new Nafta(x,y,m.get("Nafta"));
					premios.add(p);
				}
				else if( item2 == 'b') {
					Premio p = new Balas(x,y,m.get("Balas"));
					premios.add(p);
				}
				else if (item2 == 'k') {
					Coleccionable I = new Cono(x,y,m.get("Cono"));
					coleccionables.add(I);	
				}
				else if (item2 == 'z') {
					Coleccionable I = new Baliza(x,y,m.get("Baliza"));
					coleccionables.add(I);	
				}
				else if( item2 == '$') {
					crearPremioRandom(x,y);
					Planta p = new Planta(x,y,m.get("Planta"));
					intransitables.add(p);
					destructibles.add(p);
				}
				else if (item2 == 'e'){
					crearPremioRandom(x,y);
					Pared p = new Pared(x,y,m.get("Pared"));
					intransitables.add(p);
					destructibles.add(p);
				}

				x+= SPACE;
			}
			else if ( item == 's') {
				Arena T = new Arena(x,y,m.get("Arena"));
				transitables.add(T);
				if( item2 == 'c') {
					crearPremioRandom(x,y);
					Caja c = new Caja(x,y,m.get("Caja"));
					intransitables.add(c);
					destructibles.add(c);
				}
				else if( item2 == 'p') {
					Premio p = new Puntos(x,y,m.get("Puntos"));
					premios.add(p);
				}
				else if( item2 == 'n') {
					Premio p = new Nafta(x,y,m.get("Nafta"));
					premios.add(p);
				}
				else if( item2 == 'b') {
					Premio p = new Balas(x,y,m.get("Balas"));
					premios.add(p);
				}
				else if (item2 == 'k') {
					Coleccionable I = new Cono(x,y,m.get("Cono"));
					coleccionables.add(I);	
				}
				else if (item2 == 'z') {
					Coleccionable I = new Baliza(x,y,m.get("Baliza"));
					coleccionables.add(I);	
				}
				else if( item2 == '$') {
					crearPremioRandom(x,y);
					Planta p = new Planta(x,y,m.get("Planta"));
					intransitables.add(p);
					destructibles.add(p);
				}
				else if (item2 == 'e'){
					crearPremioRandom(x,y);
					Pared p = new Pared(x,y,m.get("Pared"));
					intransitables.add(p);
					destructibles.add(p);
				}

				x+= SPACE;
			}

			h = y;
		}
		if(tipoRobot == "Militar")
			robot = new Militar(xInicial, yInicial,this);
		else
			robot = new Civil(xInicial, yInicial,this);

	}


	/**
	 * Consulta los transitables del nivel.
	 *
	 * @return transitables, lista de transitables del nivel.
	 */
	public ArrayList<Transitable> getTransitables() {
		return transitables;
	}


	/**
	 * Consulta los intransitables del nivel.
	 *
	 * @return intransitables, lista de intransitables del nivel.
	 */
	public ArrayList<Intransitable> getIntransitables() {
		return intransitables;
	}

	/**
	 * Consulta los destructibles del nivel.
	 *
	 * @return transitables, lista de transitables del nivel.
	 */
	public ArrayList<Destructible> getDestructibles() {
		return destructibles;
	}

	/**
	 * Consulta los indestructibles del nivel.
	 *
	 * @return indestructibles, lista de indestructibles del nivel.
	 */
	public ArrayList<Indestructible> getIndestructibles() {
		return indestructibles;
	}


	/**
	 * Consulta los premios del nivel.
	 *
	 * @return premios, lista de premios del nivel.
	 */
	public ArrayList<Premio> getPremios() {
		return premios;
	}


	
	
	/**
	 * Consulta la coordenada x de la posicion inicial del robot.
	 *
	 * @return xInicial, coordenada x donde inicia el robot en el nivel.
	 */
	public int getxInicial() {
		return xInicial;
	}


	/**
	 * Consulta la coordenada y de la posicion inicial del robot.
	 *
	 * @return yInicial, coordenada y donde inicia el robot en el nivel.
	 */
	public int getyInicial() {
		return yInicial;
	}


	/**
	 * Consulta la coordenada x de la posicion de la llegada.
	 *
	 * @return xFinal, coordenada x donde deberia llegar el robot en el nivel.
	 */
	public int getxFinal() {
		return xFinal;
	}


	/**
	 * Consulta la coordenada y de la posicion de la llegada.
	 *
	 * @return yFinal, coordenada y donde deberia llegar el robot en el nivel.
	 */
	public int getyFinal() {
		return yFinal;
	}
	
	/**
	 * Consulta el robot del mapa.
	 *
	 * @return robot, es el robot del mapa.
	 */
	public Robot getRobot() {
		return robot;
	}
	
	/**
	 * Consulta si el robot tiene la posicion de la llegada.
	 *
	 * @return completed, verdadero si el robot tiene la posicion de la llegada.
	 */
	public boolean getCompleted() {
		return completed;
	}


	/*
	public void paint(Graphics g) {
		super.paint(g);
		buildWorld(g);
	}
	*/


	/**
	 * Consulta el ancho del mapa.
	 *
	 * @return w, el ancho del mapa.
	 */
	public int getW() {
		return w;
	}


	/**
	 * Cambia el ancho del mapa.
	 *
	 * @param w es el nuevo ancho del mapa.
	 */
	public void setW(int w) {
		this.w = w;
	}


	/**
	 * Consulta el alto del mapa.
	 *
	 * @return h, el alto del mapa.
	 */
	public int getH() {
		return h;
	}

	/**
	 * Cambia la altura del mapa.
	 *
	 * @param h nueva altura del mapa.
	 */
	public void setH(int h) {
		this.h = h;
	}


	/**
	 * Chequea la colision de un disparo.
	 */
	public void checkCollisions() {


		ArrayList<Disparo >ds = disparos;

		for (int i = 0; i < ds.size(); i++) {
			Disparo d = (Disparo) ds.get(i);

			Rectangle r1 = d.getBounds();

			for (int j = 0; j<intransitables.size(); j++) {
				Intransitable a = intransitables.get(j);
				Rectangle r2 = a.getBounds();

				if (r1.intersects(r2)) {
					d.setVisible(false);
					a.recibirDisparo();
				}
			}
		}
	}



	/**
	 * Chequea si el nivel fue completado.
	 */
	public void isCompleted() {
		if(robot.getX() == xFinal && robot.getY() == yFinal) {
			completed = true;
			guiJuego.cambiarMusica("/Audio/Joe_Esposito_Youre_the_best.wav");
		}
	}


	/**
	 * Reinicia el nivel actual.
	 */
	public void restartLevel() {

		intransitables.clear();
		indestructibles.clear();
		transitables.clear();
		destructibles.clear();
		coleccionables.clear();
		premios.clear();
		pinturas.clear();
		robot.vaciarBaul();

		initWorld();
		if (completed) {
			completed = false;
		}
		puntaje = 0;
		guiJuego.actualizarPuntos();
		guiJuego.actualizarNafta();
		guiJuego.actualizarBalas();
		guiJuego.actualizarItemEnBrazo();
		guiJuego.actualizarBaul();
		guiJuego.cambiarMusica("/Audio/Hydrogen.wav");
	}


	/**
	 * Mueve todos los disparos en el mapa y elemina de las listas los que ya colisionaron.
	 */
	public void accion() {

		ArrayList<Disparo> ds = disparos;

		for(int i = 0 ; i < ds.size() ; i++) {
			Disparo d = (Disparo) ds.get(i);
			if(d.isVisible())
				d.move();
			else
				ds.remove(i);
		}

		checkCollisions();
		//repaint();  
	}

	/**
	 * Crea premio random.
	 *
	 * @param x coordenada x donde se creara el premio.
	 * @param y coordenada y donde se creara el premio.
	 */
	public void crearPremioRandom(int x, int y) {
		int rand = (int) (Math.random() * (10 - 0) + 1);

		if(rand == 7) {
			Premio p = new Nafta(x,y,m.get("Nafta"));
			premios.add(p);
		}
		else if(rand == 8) {
			Premio p = new Balas(x,y,m.get("Balas"));
			premios.add(p);
		}
		else if (rand == 9 || rand == 10) {
			Premio p = new Puntos(x,y,m.get("Puntos"));
			premios.add(p);
		}
	}
	
	/**
	 * Consulta el ancho del mapa.
	 *
	 * @return w, el ancho del mapa.
	 */
	public int getMapWidth() {
		return w;
	}


	/**
	 * Consulta el alto del mapa.
	 *
	 * @return h, el alto del mapa.
	 */
	public int getMapHeight() {
		return h;
	}


	/**
	 * Consulta el puntaje.
	 *
	 * @return puntaje.
	 */
	public int getPuntaje() {
		return puntaje;
	}

	/**
	 * Consulta el item en el brazo del rebot.
	 *
	 * @return item, coleccionable en el brazo del robot.
	 */
	public Coleccionable getItem() {
		return robot.getItemEnBrazo();
	}

	/**
	 * Consulta la nafta del robot.
	 *
	 * @return nafta, nafta actual del robot.
	 */
	public int getNafta() {
		return robot.getNafta();
	}

	/**
	 * Consulta de la cantidad de balas del robot.
	 *
	 * @return balas, cantidad de balas actual del robot.
	 */
	public int getBalas() {
		return robot.getBalas();
	}


	/**
	 * Cambia el puntaje del robot.
	 *
	 * @param puntaje nuevo puntaje del robot.
	 */
	public void setPuntaje(int puntaje) {
		this.puntaje = puntaje;
	}

	/**
	 * Consulta los disparos en el mapa.
	 *
	 * @return disparos, los disparos del mapa.
	 */
	public ArrayList<Disparo> getDisparos() {
		return disparos;
	}

	/**
	 * Consulta los coleccionables del mapa.
	 *
	 * @return coleccionables, los coleccionables del mapa.
	 */
	public ArrayList<Coleccionable> getColeccionables() {
		return coleccionables;
	}
	
	/**
	 * Consulta las pinturas del mapa.
	 *
	 * @return pinturas, las pinturas del mapa.
	 */
	public ArrayList<Pintura> getPinturas() {
		return pinturas;
	}

	/**
	 * Cambia la gui del juego.
	 *
	 * @param g es la nueva gui del juego.
	 */
	public void setGUI(GUIJuego g) {
		guiJuego = g;
	}
	
	/**
	 * Agrega un coleccionable a la lista de coleccionables del mapa.
	 *
	 * @param c nuevo coleccionable que se agregara a la lista.
	 */
	public void agregarColeccionable(Coleccionable c){
		coleccionables.add(c);		
	}
	
	/**
	 * Agrega una pintura a la lista de coleccionables del mapa.
	 *
	 * @param p nueva pintura que se agregara a la lista.
	 */
	public void agregarPintura(Pintura p){
		pinturas.add(p);
	}

	/**
	 * Consulta el mapeo del mapa.
	 *
	 * @return mapeo, mapeo (clase->imagen) del mapa.
	 */
	public Mapeo getMapeo(){
		return m;
	}

	

}